#ifndef DISK_MANAGER_H
#define DISK_MANAGER_H

#include "../includes/DiskDriver.h"
#include <cstddef>
#include <stdio.h>
#include <sys/types.h>

#define SUPER_BLOCK_SIZE 420 //超级块的大小
#define INODE_NUM 96 //inode表的条目数
#define INODE_SIZE 1164 // 每个inode的大小
#define DATA_NUM 32000 // 数据区的数据块数量
#define PATH_LEN 128 // 文件路径的最大长度
#define BLOCKS_NUM 256 // 每个inode最多串联的数据块个数
#define BLOCK_SIZE 1024 // 每个数据块的大小

class DiskManager {
    
public:
    // 超级块结构体定义
    #pragma pack(push, 1)
    struct SuperBlock{
        off_t inode_start; // 4B
        off_t data_start; // 4B
        bool inode_state[INODE_NUM]; // 最多创建96个文件, 12B
        bool data_state[DATA_NUM]; // 400B

        // 默认构造函数
        SuperBlock() : inode_start(0), data_start(0) {
            // 初始化数组为false（表示所有inode和数据块都未使用）
            memset(inode_state, false, sizeof(inode_state));
            memset(data_state, false, sizeof(data_state));
        }
    };
    #pragma pack(pop)

    // inode结构体定义
    #pragma pack(push, 1)
    struct Inode{
        int id; // 该节点在inode节点表中的标识, 同时也能代表该节点在inode节点表的位置, 4B
        size_t size; // 该节点所代表的文件的大小, 4B
        int block_num; // 该节点拥有的数据块个数, 4B
        char path[PATH_LEN]; // 文件名长度最大为128个字符, 128B
        int blocks[BLOCKS_NUM]; // 每个文件最多包含256个数据块, 1024B

        // 默认构造函数
        Inode() : id(-1), size(0), block_num(0) {
            // 初始化路径为空字符串
            memset(path, 0, sizeof(path));
            // 初始化blocks数组为-1（表示无效的块ID）
            for (int i = 0; i < BLOCKS_NUM; ++i) {
                blocks[i] = -1;
            }
        }
    };
    #pragma pack(pop)

    static DiskManager& getInstance(const std::string &path = "");
    ~DiskManager();

    // 禁止拷贝和移动
    DiskManager(const DiskManager&) = delete;
    DiskManager& operator=(const DiskManager&) = delete;
    DiskManager(DiskManager&&) = delete;
    DiskManager& operator=(DiskManager&&) = delete;

    int super_block_clear(); // 格式化超级块, 将磁盘置为空的状态
    int super_block_load(SuperBlock &super_block); // 加载超级块信息到内存, 能够看到磁盘当前的占用状态以及磁盘的分区情况, 读取到的信息将会保存到super_block引用中
    int super_block_set(SuperBlock &super_block); // 修改超级块的状态, 写入到磁盘

    int new_inode(const std::string &path); // 创建一个新的inode, 创建失败返回-1, 创建成功返回该inode的id
    int inode_del(int id); // 根据id查询, 删除一个inode, 删除失败返回-1
    int inode_del(const std::string &path); // 根据文件路径查询, 删除一个inode, 删除失败返回-1
    int inode_get(const std::string &path, Inode &inode); // 根据文件路径查询其所对应的inode, 查询失败返回-1, 查询成功将把信息填写到inode引用中 
    int inode_get(int id, Inode &inode); // 根据id查询其所对应的inode, 查询失败返回-1, 查询成功将把信息填写到inode引用中 
    int inode_set(int id, Inode &inode); // 修改inode的值
    off_t inode_id_to_offset(int id); // 将inode表索引(id)转换为实际的磁盘地址偏移量

    int new_data_block(); // 从数据区分配一个数据块, 块大小为1024B, 返回该块在数据区的位置索引, 分配失败返回-1
    int data_block_del(int id); // 删除第id个数据块
    int data_block_write(int id, void* buff, size_t size, off_t inner_off); // 在第id个数据块中写入大小为size的数据, 块内数据偏移量为inner_off
    int data_block_read(int id, void* buff, size_t size, off_t inner_off); // 从第id个数据块中读取大小为size的数据, 块内数据偏移量为inner_off
    off_t data_block_id_to_offset(int id); // 将数据块索引转为实际的磁盘地址偏移量
    
public:
    SuperBlock super_block_;

private: 
    // 私有构造函数
    DiskManager(const std::string &path);

    std::string file_path_;
    static DiskManager* instance_;
};

#endif